---

---

```java title=''
package annotations;

import onjava.atunit.Test;

public class Testable {
  public void execute() {
    System.out.println("Executing...");
  }
  @Test
  void testExecute() {
    execute();
  }
}
```

testExecute() 方法增加了 @Test 注解，增加了注解的方法和其它方法相比并无区别。

## 定义注解

下面是对 @Test 注解的定义，非常像接口的定义。注解和其它 Java 接口一样，也会编译成类文件。

```java title=''
package onjava.atunit;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}
```
注解的定义必须要有<RedSpan>元注解</RedSpan> @Target 和 Retention 。@Target 定义了可以在何处使用该注解，@Retention 定义了该注解在源代码（SOURCE）、类文件（CLASS）或运行时（RUNTIME）中是否可用。

注解通常包含一些可以设定值的 <RedSpan>元素</RedSpan>。程序或工具在处理注解时可以使用这些参数。元素看起来比较像接口方法，只不过可以为其设定默认值。

没有任何元素的注解称为标记注解（如 @Test）


下面是一个用于跟踪某项目中用例的简单注解，程序员会给某个特定用例所需的所用方法或方法集都加上注解。项目经理可以通过计算已实现的用例数来了解项目的进度，维护项目的开发人员可以轻松地找到需要维护的用例，或者在系统内调试业务规则。

```java title=''
package annotations;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
  int id();
  String description() default "no description";
}

```

id 属性是必须的，而 description 属性是可选的。id 类型会受到编译器的类型检查，所以可以用它跟踪数据库链接到用例文档和源代码。

下面这个类，其中的 3 个方法被注解为用例。

```java title=''
package annotations;

import java.util.List;

public class PasswordUtils {

  @UseCase(id=47,description = "Password must contain at least one numeric")
  public boolean validatePassword(String passwd) {
    return (passwd.matches("\\w*\\d\\W*"));
  }

  @UseCase(id=48)
  public String encryptPassword(String password) {
    return new StringBuilder(password).reverse().toString();
  }
  @UseCase(id=49,description = "New passwords can't equal previously used ones")
  public boolean checkForNewPassword(List<String> prePasswords, String password) {
    return !prePasswords.contains(password);
  }
}

```

## 元注解
Java 语言中目前只定义了 5 个标准注解和 5 个元注解，元注解是为了对注解进行注解。

### @Target
表明该注解可使用的地方，可选的 ElementType 参数包括：
* CONSTRUCTOR： 构造器声明
* FIELD： 字段声明（包括枚举常量）
* LOCAL VARIABLE： 本地变量声明
* METHOD ： 方法声明
* PACKAGE ： 包声明
* PARAMETER： 参数声明
* TYPE： 类、接口（包括注解类型）或枚举的声明

### @Retention
表明注解信息可以保留多久，可选的 RetentionPolicy 参数包括：
* SOURCE：注解会被编译器丢弃
* CLASS：注解在类文件中可以被编译器使用，但会被虚拟机丢弃
* RUNTIME：注解在运行时仍被虚拟机保留，因此可以通过反射读取到注解信息

### @Documented
在 Javadoc 中引入该注解

### @Inherited
允许子类继承父注解

### Repeatable
可以多次应用于同一个声明

